package qotwReader.question;

import java.awt.image.BufferedImage;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.UnknownHostException;

import javax.imageio.ImageIO;

import qotwReader.types.EbookType;
import qotwReader.utils.Filenames;


import net.htmlparser.jericho.*;

public class QuestionFile
{
    final private Source questionSource;
    private OutputDocument questionOutputSource;
    final private QuestionData metadata;
    
    final private File outputFile;
    
    public QuestionFile(QuestionHTML html, QuestionData metadata) throws IOException
    {
        this.questionSource = html.getQuestionSource();
        this.questionOutputSource = new OutputDocument(questionSource);
        this.metadata = metadata;
        
        String title = metadata.getFilesafeTitle();
        String date = metadata.getFilesafeDate();
        this.outputFile = new File(Filenames.getFilename(EbookType.html, title, date));
        
        saveToFile();
        //TODO what want to actually do is to try and open the file
        // if it exists use it, don't need to save it.
        
        //TODO would be nice to save html files to /html/ and ebooks to /ebook/type/
    }
    
    private void saveToFile() throws IOException
    {
        saveImages();

        writeSourceToFile();
    }
    
    private File writeSourceToFile() throws IOException
    {
        FileWriter fileWriter = new FileWriter(outputFile);
        BufferedWriter htmlOut = new BufferedWriter(fileWriter);
        // write the html to file
        htmlOut.write(questionOutputSource.toString());
        
        htmlOut.close();
        
        return outputFile;
    }
    
    /**
     * Download all images used in a question
     * Need to save the images to file and change the source to point to the locally saved files.
     * @param questionTitle The title of the question these images are being downloaded from.
     */
    private void saveImages()
    {
        // get all image tags
        for (Element e : questionSource.getAllElements(HTMLElementName.IMG))
        {
            // get the image location
            final String sourceImageURL = e.getAttributeValue("src");
            
            if (sourceImageURL != null)
            {
                String localLocationToSave;
                String imageURL;
                                
                // if it starts with / it's a relative image.
                if (sourceImageURL.startsWith("/"))
                {
                    // need to save it in the image folder, if not there already.
                    imageURL = Filenames.b3taAddress + sourceImageURL;
                    
                    // remove the first slash, otherwise it prints to the hard drive, not relative.
                    localLocationToSave = (String) sourceImageURL.subSequence(1, sourceImageURL.length());
                }
                // if it starts with http it's an external image
                else if (sourceImageURL.startsWith("http://"))
                {
                    // get the image name. Save it to /image/questiontitle/imagename.jpg
                    
                    String[] split = sourceImageURL.split("[*/*]|[*=*]"); // split around forwards slashes or equals
                    localLocationToSave =
                          "images"
                        + File.separator + metadata.getFilesafeTitle()
                        + File.separator + split[split.length - 1];
                    imageURL = sourceImageURL;
                    
                }
                else // don't know what we're dealing with, ignore this image, do not save
                    continue;
                
                // replace the file separators with the local verison.
                localLocationToSave = localLocationToSave.replace('/', File.separatorChar);
                
                // update the source to point to the new file location - not the image on the internet.
                String elementSource = e.toString();
                elementSource = elementSource.replace(sourceImageURL, localLocationToSave);
                questionOutputSource.replace(e.getBegin(), e.getEnd(), elementSource);

                // save the image at imageURL to localLocationToSave
                saveImageToFile(imageURL, localLocationToSave);
            }
        }
    }
    
    private void saveImageToFile(String imageURL, String localLocationToSave)
    {
        try
        {
            final URL url = new URL(imageURL);
            
            final BufferedImage image = ImageIO.read(url);
                        
            if (image == null)
            {
                System.out.println("Image could not be read from URL '" + url.toString() + "'. Skipping saving image");
                return;
            }
            
            File imageFile = new File(outputFile.getParent(), localLocationToSave);
            
            // make the parent directories to save the image into
            imageFile.getParentFile().mkdirs();
            
            boolean fileCreated = imageFile.createNewFile();
            
            if (fileCreated == true) // named file sucessfully created, it did not previously exist
            {
                String[] findFullStop = imageURL.split("\\."); // this is regex for a full stop         
                String imageFiletype = findFullStop[findFullStop.length - 1]; // get the last element - it's the filetype
                
                
                //System.out.println("File written " + localLocationToSave);
                ImageIO.write(image, imageFiletype, imageFile);
            }
            else
            {
                //System.out.println("File already exists " + localLocationToSave);
                return; // named file already exists or could not be created
            }
        }
        catch (MalformedURLException e)
        {
            System.out.println("Tried saving image, but could not read URL. Skipping saving image.");
            e.printStackTrace();
        }
        catch (IOException e)
        {
            if (e.getCause() != null && e.getCause().getClass().equals(UnknownHostException.class))
            {
                System.out.println("Could not download the image " + imageURL);
                System.out.println("Unknown host exception (Might be a 404?)");
                return;
                
            }
            System.out.println("Error saving file to disk.");
            System.out.println("Image url: " + imageURL);
            e.printStackTrace();
        }
    }

    public File getOutputFile() { return outputFile; }
}
